package com.easyexcel.write;

import java.io.IOException;
import java.util.*;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import com.easyexcel.annotation.Excel;
import com.easyexcel.util.ExcelUtil;
import com.easyexcel.write.style.CommonCellStyle;
import com.easyexcel.write.style.MyCellStyle;
import com.easyexcel.write.util.WriteListExcelHelp;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

public class WriteListExcel<T> implements WriteExcel<T>{
	private MyCellStyle cellStyle;
	private boolean isNeedSequence;
	private Workbook workbook;
	private Sheet sheet;
	private int beginNum = 1;
	private int sheetSize;
	private String outFilePath;
	private String sheetName = "sheet";
	@Override
	public boolean write(Map<String,Object> param,List<T> list) throws IOException, IllegalArgumentException, IllegalAccessException {
		initParam(param,list.get(0).getClass());
		if(workbook instanceof HSSFWorkbook && sheetSize == 0 && list.size() > 65535)
			sheetSize = 65535;
		if(workbook instanceof SXSSFWorkbook && sheetSize == 0 && list.size() > 1048575)
			sheetSize = 1048575;
		WriteListExcelHelp<T> help = new WriteListExcelHelp<T>(cellStyle);
		if(sheetSize!=0 && list.size()>sheetSize){
			LinkedList<T> ll = new LinkedList<>(list);
			list.clear();
			double sn = (double)ll.size()/sheetSize;
			sn = Math.ceil(sn);
			int initBeginNum = beginNum;
			Iterator<T> it = ll.iterator();
			for(int i=1;i<=sn;i++){
				beginNum = initBeginNum;
				sheet = workbook.createSheet(sheetName+"-"+i);
				help.generateHeader(sheet, beginNum, ll.getFirst().getClass());
				help.setSequence(1);
				for(int j=0;j<sheetSize;j++){
					if(it.hasNext()){
						help.generateBody(sheet,++beginNum,it.next());
						it.remove();
					}
				}
			}
		}else{
			sheet = workbook.createSheet(sheetName);
			help.generateHeader(sheet,beginNum,list.get(0).getClass());
			for(T t : list){
				help.generateBody(sheet, ++beginNum, t);
			}
		}
		ExcelUtil.workbookToFile(workbook,outFilePath);
		return true;
	}

	private void initParam(Map<String, Object> param, Class clazz) {
		Excel excel = (Excel) clazz.getAnnotation(Excel.class);
		com.easyexcel.annotation.Sheet s = (com.easyexcel.annotation.Sheet) clazz.getAnnotation(com.easyexcel.annotation.Sheet.class);
		if(excel != null){
			isNeedSequence = excel.isNeedSequence();
			outFilePath = excel.outFilePath();
			beginNum = excel.beginRow();
		}
		if(s != null){
			sheetName = s.sheetName();
			sheetSize = s.sheetSize();
		}
		if(param == null){
			workbook = new HSSFWorkbook();
			cellStyle = new CommonCellStyle(workbook);
		}else{
			if(param.get("workbook") == null){
                workbook = new HSSFWorkbook();
            }else{
                workbook = (Workbook) param.get("workbook");
                if(workbook instanceof  XSSFWorkbook)
                    workbook = new SXSSFWorkbook();
            }
			if(param.get("myCellStyle") == null)
				cellStyle = new CommonCellStyle(workbook);
			else
				cellStyle = (MyCellStyle)param.get("myCellStyle");
			if(param.get("outFilePath") != null)
				outFilePath = param.get("outFilePath").toString();
			if( param.get("beginRow") != null)
				beginNum = Integer.parseInt(param.get("beginRow").toString());
		}
	}
	
}
